/* 
 * File:   prepare_service.h
 * Author: james
 *
 * Created on 2011年4月2日, 上午10:48
 */

#ifndef PREPARE_SERVICE_H
#define	PREPARE_SERVICE_H

#include <string>
#include <vector>
#include <map>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/thread/thread.hpp>
#include <boost/pool/object_pool.hpp>

#include "conf_parser.h"
#include "prepare_connection.h"
#include "prepare.h"

namespace edm
{
    namespace prepare
    {
        //! define prepare service
        //! service main work:
        //! 1. callback for net client service
        //! 2. timer to retry for blocking msp
        class prepare_service_t
        {
        public:
            prepare_service_t(const char* bind, const std::string& host, const std::string& port, const std::string& msp_control);
            ~prepare_service_t();
            
            //! set init block msp
            void block(std::vector<std::string>& blocks);
            
            //! start prepare service
            int start(delivery_handler_t delivery_handler);
            
            //! stop prepare service
            int stop();
                        
            //! prepare connection connect callback handler
            void callback_connect(edm::network::connection_ptr_t c);

            //! prepare connection message callback handler
            void callback_handler(edm::network::connection_ptr_t c, edm::network::message_t& m);
            
            //! callback for delivery
            void callback_delivery(delivery_t* delivery);
            
            //! prepare helo response
            void prepare_status(bool with_prepare_id = false);

            //! prepare helo response
            void prepare_missed_temp(edm_task_id_t taskid);
            
            //! msp status invoke
            void msp_status(std::string& json);
            
            //! msp block invoke
            void msp_block(msp_control_t* msp, std::string& json);
            
            //! msp unblock invoke
            void msp_unblock(msp_control_t* msp, std::string& json);
        private:
            //! timer trigger for queue worker
            void timer_i();
            
            //! queue work
            void worker_i();
            
            //! delivery fsm
            void fsm_i(delivery_t* d);
            
            //! 
            bool pause(delivery_t* d);
            bool cancel(delivery_t* d);
            
            //! push to work, really proc delivery
            void push_to_work_i(delivery_t* d, bool force = false);
            
            //! push to wait for work
            void push_to_wait_i(delivery_t* d);
            void push_to_retry_i(delivery_t* d);
            void push_to_block_i(delivery_t* d);
            void push_to_stop_i(delivery_t* d);
            
            void delivery_destruct_i(delivery_t* d);
            //! prepare helo response
            void prepare_status_i(bool with_prepare_id);
            //! prepare spy response
            void prepare_spy_i();
            //! prepare helo response
            void prepare_missed_temp_i(edm_task_id_t taskid);
            
            //! prepare connection message callback handler
            void callback_handler_i(edm::network::connection_ptr_t c, edm::network::message_t& m);
            
            //! callback for delivery
            void callback_delivery_i(delivery_t* delivery);
            
            //! msp status invoke
            void msp_status_i(std::string& json);
            
            //! msp block invoke
            void msp_block_i(msp_control_t* msp, std::string& json);
            
            //! msp unblock invoke
            void msp_unblock_i(msp_control_t* msp, std::string& json);
            
            //! task status invoke
            void task_status_i(edm_task_id_t taskid, std::string& json);
        private:
            //! prepare id
            std::string m_bind_host;
            //! prepare connection to dispatch
            prepare_connection_t  m_connection;
            //! msp control config path
            std::string m_msp_control_path;
            //! msp control config parser
            edm::common::conf_parser_t m_msp_control_parser;
            //! init block msp
            std::vector<std::string> m_blocks;
            //! identify whether service is running
            bool m_started;
            //! handler for msp
            delivery_handler_t m_delivery_handler;
            //! io service object of boost for deadline time and thread working
            boost::asio::io_service m_io_service;
            //! io service work object of boost for keeping io service is running
            boost::scoped_ptr<boost::asio::io_service::work> m_io_work;
            //! the timer for loop checking timedout task
            boost::asio::deadline_timer m_timer;
            //! thread pool 
            boost::scoped_ptr<boost::thread>     m_thread;
            //! msp control map
            std::map<std::string,msp_control_t*> m_msps_map;
            std::set<msp_control_t*>             m_block_msps;
            std::set<edm_task_id_t>              m_pause_tasks;
            std::set<edm_task_id_t>              m_cancel_tasks;
            
            //! deliverys queues
            delivery_list_t                      m_working_deliverys;
            delivery_list_t                      m_waitting_deliverys;
            delivery_list_t                      m_retrying_deliverys;
            delivery_list_t                      m_blocking_deliverys;
            delivery_list_t                      m_stopped_deliverys;
            //! accumulates
            int   m_accepted_totals;
            int   m_catched_totals;
            //! memory pool for msp service
            boost::object_pool<msp_control_t>     m_msp_memory_pool;
            delivery_memory_pool_t                m_delivery_memory_pool;
        };
    }
}

#endif	/* PREPARE_SERVICE_H */

